#!/bin/bash

# quit when error
set -e
build_root=$PWD

# Function to check if a command exists
function command_exists {
    command -v "$1" &>/dev/null
}

# Check if sudo is available
if ! command_exists sudo; then
    echo "This script requires sudo privileges."
    exit 1
fi

# Check if git is installed
if ! command_exists git; then
    echo "git is not installed. Please install git first."
    exit 1
fi

# Function to configure the build environment
function environment {
    echo "Configure the build environment"
    
    # Install packages
    echo "install packages ..."
    sudo yum install -y libseccomp-devel patch

    # Check if Rust is installed by yum, uninstall if necessary
    if rpm -q rustc &>/dev/null; then
        echo "version of the rust installed by yum too high, uninstalled and reinstall 1.69.0 by rustup"
        sudo yum remove -y rust cargo
    fi

    # Install rustup if not already installed
    if ! command_exists rustup; then
        echo "install rustup"
        curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
        source ~/.bashrc
    else
        echo "rustup installed"
    fi

    # Set default Rust version to 1.69.0
    echo "set default Rust 1.69.0 ..."
    rustup default 1.69.0
    echo "Rust default set success."

    # Add RISC-V toolchain target
    echo "add RISC-V tool-chain target ..."
    rustup target add riscv64gc-unknown-linux-gnu

    # Check if Go is installed
    if ! command_exists go; then
        echo "can't find Go, starting install..."
        
        if [ ! -e $build_root/go_golang ]; then
            echo "clone go_golang ..."
            git clone https://gitee.com/huang_a/go_golang.git
        fi
        
        export PATH=$build_root//go_golang/go/bin:$PATH
        chmod +x $build_root//go_golang/go/bin/go
        export GOROOT=$build_root//go_golang/go
        export GOPATH=$build_root//go_golang/golang
        echo "go_golang cloned success, env setted."

        # Configure Go Proxy
        echo "config Go Proxy ..."
        go env -w GOPROXY=https://goproxy.cn
        echo "Go Proxy config success."
    else
        go version
    fi

    # Install yq
    if ! command_exists rustup; then
        echo "install yq ..."
        go install github.com/mikefarah/yq/v4@latest
        echo "yq install success."
    else
        echo "yq installed"
    fi
    
}

# Function to clone and build kata-containers
function kata_base {
    # Clone kata-containers repository if it doesn't exist
    if [ ! -e $build_root/kata-containers ]; then
        echo "clone kata-containers ..."
        git clone https://gitee.com/src-openeuler/kata-containers.git
    fi

    cd $build_root/kata-containers
    echo "kata-containers clone success, going to the directory."

    # Apply patches
    echo "apply patches ..."
    ./apply-patches

    
    if [[ -f ./patch_flag_h ]];then
       echo "patched!"
    else
       cat $build_root/patches.conf | while read line
       do
          if [[ $line == '' || $line =~ ^\s*# ]]; then
              continue
          fi
          echo "====patch $line======"
          patch -p1 -F1 -s < $build_root/patches/$line
       done
       touch ./patch_flag_h 
    fi  

    # Build libs, agent, runtime
    echo "build libs, agent, runtime ..."
    make libs agent runtime
    echo "libs, agent, runtime build success."
    
    # Install runtime
    sudo chmod +x -R .
    echo "install runtime ..."
    install -p -m 750 src/runtime/kata-runtime /usr/bin/
    install -p -m 750 src/runtime/kata-monitor /usr/bin/
    install -p -m 750 src/runtime/containerd-shim-kata-v2 /usr/bin/
    install -p -m 640 -D src/runtime/config/configuration-qemu.toml /usr/share/defaults/kata-containers/configuration.toml
    install -p -m 640 -D src/runtime/config/configuration-stratovirt.toml /usr/share/defaults/kata-containers/configuration-stratovirt.toml
    echo "build && install successful"
}

# Function to build the kernel
function kernel {
    echo "build kernel"

    if [ ! -e $build_root/kernel-6.6.0-74.0.0 ]; then
        wget https://gitee.com/openeuler/kernel/repository/archive/6.6.0-74.0.0.zip || { echo "Download failed!"; exit 1; }
        unzip 6.6.0-74.0.0.zip
    fi

    cd $build_root/kernel-6.6.0-74.0.0
    cp arch/riscv/configs/openeuler_defconfig ./.config
    make olddefconfig
    sudo make -j$(nproc)

    mkdir -p -m 755 /var/lib/kata
    install -p -m 755 -D arch/riscv/boot/Image /var/lib/kata/kernel
    sudo mkdir /usr/share/kata-containers
    sudo ln -sf /var/lib/kata/kernel /usr/share/kata-containers/vmlinux.container
}

# Function to build initrd image
function initrd_img {
    echo "build kata-containers-initrd.img"

    if [ ! -e $build_root/kata-containers ]; then
        git clone https://gitee.com/src-openeuler/kata_integration.git
    fi

    cd $build_root/kata_integration
    ./apply-patches
    mkdir -p -m 750 build
    cp $build_root/kata-containers/src/agent/target/riscv64gc-unknown-linux-gnu/release/kata-agent build/
    
    sudo yum install busybox conntrack-tools ipvsadm nfs-utils -y
    sudo systemctl start nfs-server

    sudo make initrd
    sudo install -p -m 640 ./build/kata-containers-initrd.img /var/lib/kata/
    sudo chmod +x -R /var/lib/kata/
}

# Function to build rootfs
function rootfs {
    echo "build rootfs"
    cd $build_root/kata-containers/tools/osbuilder/rootfs-builder
    export TARGET_ARCH=riscv64
    export ARCH=riscv64
    export CROSS_BUILD=true
    export AGENT_INIT=yes  # Use kata-agent as init
    export ROOTFS_DIR=.  # Specify the target rootfs directory
    export AGENT_SOURCE_BIN=/usr/bin/kata-agent
    
    sudo ./rootfs.sh openeuler
    cd rootfs-openEuler
    sudo ./usr/bin/systemctl daemon-reload
}

# Function to build kata-containers.img
function kata_containers_img {
    echo "build kata-containers.img"
    cd $build_root/kata-containers/tools/osbuilder/image-builder
    sudo ./image_builder.sh ../rootfs-builder/rootfs-openEuler/
    sudo install -p -m 640 kata-containers.img /usr/share/kata-containers/
}

function show_help {
    echo "Usage: $0 [OPTIONS]"
    echo "Options:"
    echo "  --environment           Configure the build environment (install dependencies)"
    echo "  --kata_base             Clone kata-containers and build libs agent runtime"
    echo "  --kernel                Build the kernel for Kata Containers"
    echo "  --initrd_img            Build the initrd image for kata-containers：kata-containers-initrd.img"
    echo "  --rootfs                Build the root filesystem for kata-containers"
    echo "  --kata_containers_img   Build the kata-containers.img"
    echo "  --h                     Show this help message"
    echo ""
    echo "If no function is specified, all functions will be executed in sequence."
}

# Main script execution
if [ $# -eq 0 ]; then
    echo "No function specified. Executing all functions..."
    environment 
    kata_base
    kernel
    initrd_img
    rootfs
    kata_containers_img
elif [[ "$1" == "--h" ]]; then
    show_help
else
    # Execute specified functions
    for func in "$@"; do
        case "$func" in
            --environment)
                environment
                ;;
            --kata_base)
                kata_base
                ;;
            --kernel)
                kernel
                ;;
            --initrd_img)
                initrd_img
                ;;
            --rootfs)
                rootfs
                ;;
            --kata_containers_img)
                kata_containers_img
                ;;
            *)
                show_help
                exit 1
                ;;
        esac
    done
fi
